package com.dq.demos.web.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alipay.mychain.gov.sdk.base.DecryptAndVerifyUtils;
import com.alipay.mychain.gov.sdk.base.FileResultZww;
import com.alipay.mychain.gov.sdk.base.GenericResult;
import com.dq.demos.web.service.IZLBToYFKService;
import com.dq.demos.web.utils.HttpUtils;
import com.dq.demos.web.utils.InvoiceOfdUtil;
import com.dq.demos.web.utils.YFKFormatDataUtil;
import com.nuonuo.plate.extracte.BaseExtracte;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

@Service
public class ZLBToYFKServiceImpl implements IZLBToYFKService {
    private static Logger logger = LoggerFactory.getLogger(InvoiceOfdUtil.class);
    //填税号，nsrsbh，查询公司的税号
    private static String instCode          = "123305214712205444";
    //填私钥秘钥，password，税局密码
    private static String password          = "t8c5SZxNo9gdqyTR";
    //填秘钥，pkcs8PrivateKey，税局密钥（证书）
    private static String privateKeyContent = "-----BEGIN ENCRYPTED PRIVATE KEY-----\n" +
            "MIH6MFUGCSqGSIb3DQEFDTBIMCcGCSqGSIb3DQEFDDAaBBQ1q5SSJCbGzH3x4ZwD\n" +
            "hbku7fReqwICCAAwHQYJYIZIAWUDBAEqBBA0tFuwuulSgYGksmT8AQusBIGg2YBC\n" +
            "lx4+N9MMTSZ/30klZ3deeNEMEIdgJS00/UbvT/aqjvqqnoV/ZLrNejbUqnOhjDTW\n" +
            "+InSw1P+Zp6k+K4cj+KMUtbNzTTTdZ3FBN1IEwCe52U7ibVbOmkoSemMH3rHPpIv\n" +
            "yCnIGbkQbg6xUWoc6alURXDaiQtRLixTuDF3inKDWNPFJOt6wo+LoYvqQa6cy28N\n" +
            "PfyCbXWqi1HUyXI/vw==\n" +
            "-----END ENCRYPTED PRIVATE KEY-----";

    @Override
    public List<JSONObject> post_zlbp_ofd(String getdate) throws Exception {
        // 获取总页数
        // 注意：每次获取总页数接口 requestId 都需要变换，  并且获取总页数和分页数据的requestId必须保持一致
        String requestId = "FFFFFFFFFFFFFF"+"_"+ System.currentTimeMillis();
        GenericResult count = packageCount(requestId, getdate, 2);
        if(count == null) return null;
        if(!count.getSuccess()){
            throw new Exception("日期: 【"+getdate+"】," + count);
        }
        JSONObject json = JSONObject.parseObject(count.getData());
        int pagecount = json.getIntValue("totalPage");
        logger.info("---->当前日期:【"+getdate+"】, 浙里办发票一共存在【"+pagecount+"】 条" );
        // OFD文件解析 // 获取分页数据和存放路径
        String bankpath = "C:\\yonyou";
//        String bankpath = SysInitQuery.getParaString("GLOBLE00000000000000", "bankpath");
        String fileDirPathSrc = bankpath + "\\" + getdate + "\\ofdjiemi1201";   // 根据自身实际路径自行修改
        String temppath = bankpath + "\\" + getdate;   // 根据自身实际路径自行修改
        checkFile(fileDirPathSrc, temppath);
        for (int i = 1; i <= pagecount; i++) {
            // 获取分页数据,并解密。  注意：获取分页数据的requestId都需要与获取总页数接口的requestId保持一致。
            GenericResult result = packageInfo(requestId, i+"");
            decryptList(result.getData(), temppath);
            logger.info("-----> " + result.getData());
        }
        // 获取刚刚下载好的文件地址解析成json数据
        List<JSONObject> lists = getOfdToJson(fileDirPathSrc, temppath);
        logger.info("--->日期:【"+getdate+"】，下载 执行成功");
        return lists;
    }


    /**
     * 解析ofd文件转为json格式数据
     * @param fileDirPathSrc
     * @param temppath
     * @return
     * @throws Exception
     */
    public List<JSONObject>  getOfdToJson(String fileDirPathSrc, String temppath) throws Exception{
        List<JSONObject> lists = new ArrayList<>();
        InputStream ins = null;
        OutputStream os = null;
        InputStream is = null;
        try {
            File file = new File(temppath);
            File[] files = file.listFiles();
            File[] var4 = files;
            int var5 = files.length;
            for(int var6 = 0; var6 < var5; ++var6) {
                File f = var4[var6];
                if (!f.getName().endsWith(".xml")) {
                    is = new FileInputStream(f);
                    BaseExtracte baseExtracte = new BaseExtracte();
                    JSONObject billjson = YFKFormatDataUtil.handlerYFKFormatData(baseExtracte.readXbrl(is), f.getPath());
                    JSONObject resJson = new JSONObject();
                    resJson.put("nsrsbh","123305214712205444"); // 默认德清
                    resJson.put("submitter","浙里办发票系统下载");
                    resJson.put("failMode","single");
                    resJson.put("multiFileMode","Y");
                    JSONObject data = billjson.getJSONObject("data");
                    JSONObject odf = billjson.getJSONObject("odf");
                    JSONArray bills = new JSONArray();
                    bills.add(data);
                    resJson.put("bills",bills);
                    JSONObject json = new JSONObject();
                    json.put("odf",odf);
                    json.put("data",resJson);
;                    lists.add(json);
                }
            }
//            List<JSONArray> listsplis = splitJSONArray(bills, 1); // 每90个位一组,上传一次发票
//            for (JSONArray arr : listsplis) {
//                JSONObject resJson = new JSONObject();
//                resJson.put("nsrsbh","123305214712205444"); // 默认德清
//                resJson.put("submitter","浙里办发票系统下载");
//                resJson.put("failMode","single");
//                resJson.put("multiFileMode","Y");
//                resJson.put("bills",arr);
//                lists.add(resJson);
//            }
//            int c = 1 / 0;
        }
        catch (IOException e) {
            throw new Exception(e);
        }finally {
            if(ins != null) {ins.close();}
            if(is != null) {is.close();}
            if(os != null) {os.close();}
        }
//        int c = 1/0;
        return lists;
    }


    /**
     * 将JSONArray每n个元素拆分成一个新的JSONArray
     * @param originalArray 原始的JSONArray
     * @param chunkSize     每个新JSONArray的元素数量
     * @return 包含拆分后JSONArray的列表
     */
    public static List<JSONArray> splitJSONArray(JSONArray originalArray, int chunkSize) {
        List<JSONArray> result = new ArrayList<>();
        JSONArray tempArray = new JSONArray();
        for (int i = 0; i < originalArray.size(); i++) {
            tempArray.add(originalArray.get(i));
            // 当达到chunkSize或者到达原始JSONArray的末尾时，将tempArray添加到结果列表中
            if ((i + 1) % chunkSize == 0 || i == originalArray.size() - 1) {
                result.add(tempArray);
                tempArray = new JSONArray(); // 重置临时JSONArray
            }
        }
        return result;
    }
    /**
     * 解析ofd文件下载到本地文件夹
     * @param dataList
     * @param fileDirPathSrc
     * @return
     * @throws IOException
     */
    public GenericResult decryptList(String dataList,String fileDirPathSrc) throws IOException {
        List<FileResultZww> fileResultZwwList = JSON.parseArray(dataList, FileResultZww.class);
        GenericResult r= new GenericResult();
        List<String> filesPath=new ArrayList<>();
        AtomicInteger total= new AtomicInteger(1);
        for(FileResultZww frz : fileResultZwwList){
            try {
                DecryptAndVerifyUtils decryptAndVerifyUtils = new DecryptAndVerifyUtils(instCode, password, privateKeyContent);
                byte[] data = decryptAndVerifyUtils.decryptZww(frz);
                String filePath = fileDirPathSrc + "\\" + frz.getFileName();  //
                DataOutputStream out = new DataOutputStream(new FileOutputStream(filePath));
                byte[] b = data;
                for (int i = 0; i < b.length; i++) {
                    out.writeByte(b[i]);
                }
                out.flush();
                out.close();
                filesPath.add(filePath);
                total.getAndIncrement();
            } catch (Exception e) {
                logger.error("----->ofd文件下载异常:"+e.getMessage());
            }
        }
        r.setSuccess(true); r.setData(JSONObject.toJSONString(filesPath));r.setErrorCode("200");
        r.setErrorMsg("解密下载完成!共解密:"+fileResultZwwList.size()+"份,成功:"+filesPath.size()+"份.");
        return r;
    }

    /**
     * 获取分页内容
     * @param pageNumber 分页数
     * @param requestId
     * @throws Exception
     */
    public static GenericResult packageInfo(String requestId,String pageNumber) throws Exception {
        JSONObject json = new JSONObject();
        json.put("nsrsbh", instCode);
        json.put("requestId", requestId);
        json.put("pageNumber", pageNumber);
        String sign = sign(json.toJSONString());
//		return post(sign, "http://zlbp.zhejiang.chinatax.gov.cn/api/zww/invoice/file/getInvoiceFilePackagesInfo");
        JSONObject requestParam = new JSONObject();
        requestParam.put("zlbUrl", "http://zlbp.zhejiang.chinatax.gov.cn/api/zww/invoice/file/getInvoiceFilePackagesInfo");
        requestParam.put("requestParam", sign);
        String tbjipprot = "127.0.0.1:7070";
//        String tbjipprot = "129.1.2.251:7070";
//        String tbjipprot = SysInitQuery.getParaString("GLOBLE00000000000000", "tbjipprot");
        return   RemoteCallPost("http://"+tbjipprot+"/zlb/downInvoice", requestParam.toString());// 远程调用
    }
    public void checkFile(String fileDirPathSrc, String temppath) {
        File file = new File(fileDirPathSrc);
        if (file.exists()) {
            System.out.println("File exists");
        } else {
            System.out.println("File not exists, create it ...");
            //getParentFile() 获取上级目录(包含文件名时无法直接创建目录的)
            if (!file.getParentFile().exists()) {
                System.out.println("not exists");
                //创建上级目录
                file.getParentFile().mkdirs();
            }
            //在上级目录里创建文件
            file.mkdirs();
        }
        File file1 = new File(temppath);
        if (file1.exists()) {
            System.out.println("File exists");
            File[] files = file1.listFiles();
            for (File in: files) {
                in.delete();
            }
            file1.delete();
            file1.mkdirs();
        } else {
            System.out.println("File not exists, create it ...");
            //getParentFile() 获取上级目录(包含文件名时无法直接创建目录的)
            if (!file1.getParentFile().exists()) {
                System.out.println("not exists");
                //创建上级目录
                file1.getParentFile().mkdirs();
            }
            //在上级目录里创建文件
            file1.mkdirs();
        }
    }
    /**
     * 获取总页数
     * @param jgrq 加工日期
     * @param requestId
     * @param gxfbs 购销方标识
     * @throws Exception
     */
    public static GenericResult packageCount(String requestId,String jgrq, int gxfbs) throws Exception {
        JSONObject json = new JSONObject();
        json.put("authorizedNsrsbh", instCode);
        json.put("gxfbs", gxfbs);
        json.put("jgrq", jgrq);
        json.put("nsrsbh", instCode);
        json.put("requestId", requestId);
        String sign = sign(json.toJSONString());
        JSONObject requestParam = new JSONObject();
        requestParam.put("zlbUrl", "http://zlbp.zhejiang.chinatax.gov.cn/api/zww/invoice/file/getInvoiceFilePackageCount");
        requestParam.put("requestParam", sign);
        String tbjipprot = "127.0.0.1:7070";
//        String tbjipprot = "129.1.2.251:7070";
//        String tbjipprot = SysInitQuery.getParaString("GLOBLE00000000000000", "tbjipprot");
        return   RemoteCallPost("http://"+tbjipprot+"/zlb/downInvoice", requestParam.toString());// 远程调用
    }


    private static GenericResult RemoteCallPost(String jsonStr, String json) throws Exception {
        String response = null;
        try {
            response = HttpUtils.sendPost(jsonStr, json.toString());;
        } catch (Exception e) {
            throw new Exception("请求下载返回异常" + e.getMessage());
        }
        GenericResult result = JSON.parseObject(response, GenericResult.class);
        logger.info("----> 请求下载发票返回信息【"+result+"】");
        return result;
    }


    /**
     * 获取签名认证
     * @param jsonStr
     * @return
     * @throws Exception
     */
    private static String sign(String jsonStr) throws Exception{
        JSONObject requestParam = new JSONObject();
        String string =  null;
        try{
            String tbjipprot = "127.0.0.1:7070";
//            String tbjipprot = "129.1.2.251:7070";
//            String tbjipprot = SysInitQuery.getParaString("GLOBLE00000000000000", "tbjipprot");
            requestParam.put("jsonStr", jsonStr);
            requestParam.put("instCode", instCode);
            requestParam.put("privateKeyContent", privateKeyContent);
            requestParam.put("password", password);
            string = HttpUtils.sendPost("http://"+tbjipprot+"/zlb/getSign", requestParam.toString());
            logger.info("-----> 浙里办签名响应【"+string+"】");
        }catch(Exception  e){
            throw new Exception("#######浙里办签名处理失败:"+e.getMessage());
        }
        return string;
    }

}
